package org.san21go.jfinfunc.financ.xirr;

import java.util.List;

import org.joda.time.Days;
import org.joda.time.LocalDate;
import org.san21go.jfinfunc.AbstractFunction;
import org.san21go.jfinfunc.FinFuncRuntimeException;
import org.san21go.jfinfunc.util.DateUtil;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;

public class XNPV extends AbstractFunction<Double> {
	private double[] amounts;
	private String[] dates;
	private double rate;

	public XNPV(double rate, double[] amounts, String[] dates) {
		super();
		this.amounts = amounts;
		this.dates = dates;
		this.rate = rate;
	}

	private double xnpv() {
		if (amounts == null || dates == null || amounts.length == 0 || dates.length != amounts.length) {
			throw new FinFuncRuntimeException("参数错误");
		}
		List<Payment> payments = Lists.newArrayList();
		for (int i = 0; i < amounts.length; i++) {
			Payment payment = new Payment();
			payment.setAmount(amounts[i]);
			payment.setDate(new LocalDate(DateUtil.formatDate(dates[i])));
			payments.add(payment);
		}

		Ordering<Payment> paymentOrdering = new Ordering<Payment>() {
			@Override
			public int compare(Payment left, Payment right) {
				return left.getDate().compareTo(right.getDate());
			}
		};
		final ImmutableList<Payment> immutablePayments = paymentOrdering.immutableSortedCopy(payments);

		double sum = 0;
		for (Payment p : immutablePayments) {
			int days = Days.daysBetween(immutablePayments.get(0).getDate(), p.getDate()).getDays();
			double t = days / 365D;
			double sub = p.getAmount() / (Math.pow((1 + rate), t));
			sum = sum + sub;
		}
		return sum;
	}

	@Override
	public Double evaluate() {
		return this.xnpv();
	}

}
